<%@ page language="java" buffer="8kb" autoFlush="true" isThreadSafe="true" isErrorPage="false"  %>
<%@ page import="java.util.*, java.util.regex.*, java.text.*, com.jamonapi.*, com.jamonapi.proxy.*, com.jamonapi.utils.*, com.fdsapi.*, com.fdsapi.arrays.*" %>

<%

FormattedDataSet fds=new FormattedDataSet();

// Set formatting rules per the requests Locale (as opposed to the servers locale).
// This will format data per the users preference (note this sets it for the given thread/servlet)
LocaleContext.setLocale(request.getLocale());

// Assign request parameters to local variables.
String action    = getValue(request.getParameter("action"),"Refresh");
String outputType= getValue(request.getParameter("outputTypeValue"),"html");
String bufferSize    = getValue(request.getParameter("bufferSize"),"No Action");
String arraySQL  = getValue(request.getParameter("ArraySQL"),"");
String sortOrder = getValue(request.getParameter("sortOrder"), "desc");
int sortCol      = getNum(request.getParameter("sortCol"), "1");
int textSize     = getNum(request.getParameter("TextSize"), "0");
String highlightString=getValue(request.getParameter("highlight"),"");

// Assign defaults for arraysql.  If nothing is provided use 'select * from array'.  If the first word is not 
// 'select' assume they want to do a like on the first column (label).
String arraySQLExec = getValue(arraySQL,"select * from array");


if (arraySQLExec.trim().toLowerCase().startsWith("select")) 
  arraySQLExec=arraySQLExec;// noop all is ok full select entered
else if (arraySQLExec.trim().toLowerCase().startsWith("where")) 
   arraySQLExec="select * from array "+arraySQL;// where clause entered:  where hits>100 and total<50000
else {
   arraySQLExec="select * from array where exceptionStackTrace like '"+arraySQL+"'";
}

arraySQLExec = (arraySQLExec.trim().toLowerCase().startsWith("select")) ? arraySQLExec : "select * from array where exceptionStackTrace like '"+arraySQL+"'";

// Build the request parameter query string that will be part of every clickable column.
String query="";
query+="&outputTypeValue="+outputType;
query+="&ArraySQL="+java.net.URLEncoder.encode(arraySQL);
query+="&TextSize="+textSize;
query+="&highlight="+highlightString;   

executeAction(action);
setBufferSize(bufferSize);


Map map=new HashMap();
// used for html page
map.put("sortPageName", "exceptions.jsp");
map.put("query", query);
map.put("imagesDir","images/");


// used for xml1 page.
map.put("rootElement", "JAMonExceptionXML");


String outputText="";
ResultSetConverter rsc=getResultSetConverter(MonProxyFactory.getExceptionDetailHeader(), MonProxyFactory.getExceptionDetail(), arraySQLExec);
ArrayConverter ac=getArrayConverter(textSize, highlightString );
fds.setArrayConverter(ac);


if (rsc.isEmpty())
  outputText="<div align='center'><br><br><b>No data was returned</b></div>";
else {  
 if ("xml".equalsIgnoreCase(outputType)) {
   rsc=new ResultSetConverter(rsc.getMetaData(), rsc.getResultSet());
   outputText=fds.getFormattedDataSet(rsc, map, "xml1");
 } else if  ("csv".equalsIgnoreCase(outputType)) {
     rsc=new ResultSetConverter(rsc.getMetaData(), ac.convert(rsc.getResultSet()));
     outputText=fds.getFormattedDataSet(rsc, map, "csv");
 } else if ("excel".equalsIgnoreCase(outputType) || "spreadsheet".equalsIgnoreCase(outputType)) {
   rsc=new ResultSetConverter(rsc.getMetaData(), ac.convert(rsc.getResultSet()));
   outputText=fds.getFormattedDataSet(rsc, map, "basicHtmlTable");
 } else 
   outputText=fds.getSortedText(rsc.getMetaData(), rsc.getResultSet(), map, sortCol, sortOrder, getJAMonTemplate(fds));
}

%>

<%
if ("html".equalsIgnoreCase(outputType)) {
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<META http-equiv="Content-Type" content="text/html"; charset=ISO-8859-1">
<link rel="stylesheet" type="text/css" href="css/JAMonStyles.css">
<title>JAMon - Exception Detail (<%=MonProxyFactory.getExceptionBufferSize()%> rows are <%=enabled(MonProxyFactory.isExceptionDetailEnabled())%>) - <%=now()%></title>
<script type="text/javascript">
<!--
// Row highlighter
var objClass

function rollOnRow(obj, txt) {
    objClass = obj.className
    obj.className = "rowon";
    obj.title = txt;
}

function rollOffRow(obj) {
    obj.className = objClass;
}

function selectAll(obj, numRows) {
    state = (obj.checked) ? true : false;

    for (var i = 1; i < numRows + 1; i ++) {
        currRow = eval("obj.form.row_" + i);
        currRow.checked = state;
    }
}

function helpWin() {
    newWin = window.open('exceptions.htm', 'helpWin', 'resizable=no,scrollbars=yes,height=550,width=450,screenX=100,screenY=100');
    if (newWin.opener == null) newWin.opener = self;
}
// -->
</script>

</head>
<body>

<!-- arraySQLExec=<%=arraySQLExec%>-->

<form action="exceptions.jsp" method="post">

<table border="0" cellpadding="1" cellspacing="0" align="center">
<tr>
<td><h2 style="color:#03487F;">JAMon - Exception Detail (<%=MonProxyFactory.getExceptionBufferSize()%> rows are <%=enabled(MonProxyFactory.isExceptionDetailEnabled())%>) - <%=now()%> - <a href="menu.jsp">Home</a></h2></td>
</tr>
<tr>
<td><table class="layoutmain" border="0" cellpadding="4" cellspacing="0" width="750" align="left">
    <tr class="sectHead">
    <th>Exception Detail Action</th>
    <th>Output</th>
    <th>Set Buffer Size (optional)</th>     
    <th>Text Display Length (optional)</th>     
    <th>Highlight (optional)</th>     
    <th>Filter (optional)</th>     
    <th align="right"><a href="javascript:helpWin();" style="color:#C5D4E4;">Help</a></th>
    </tr>
    <tr class="even">
    <th><%=fds.getDropDownListBox(actionHeader, actionBody, "")%></th>
    <th><%=fds.getDropDownListBox(outputTypeHeader, outputTypeBody, outputType)%></th>
    <th><%=fds.getDropDownListBox(bufferSizeHeader, bufferSizeBody, "")%></th>     
    <th><input type='text' name='TextSize' value="<%=(textSize<=0) ? "" : ""+textSize%>" size="15"></th>
    <th><input type='text' name='highlight' value="<%=highlightString%>" size="20"></th>     
    <th><input type='text' name='ArraySQL' value="<%=arraySQL%>" size="45"></th>
    <td><input type="submit" name="actionSbmt" value="Go !" ></td>
    </tr>
</table></td>
</tr>
<tr>
<td><table border="0" cellpadding='0' cellspacing='0' align="center">
    <tr>
    <td><%=outputText%></td>
    </tr>
</table></td>
</tr>
</table>

</form>

<br>
<div align="center" style="padding-top : 30px;">
<hr width="580" align="center" />
<a href="menu.jsp">Home</a> | <a href="jamonadmin.jsp">JAMonAdmin</a> | <a href="monmanage.jsp">Manage Mon</a> | <a href="mondetail.jsp">View Listener</a> |<a href="sql.jsp">SQL Details</a> | Exception Details
<hr width="580" align="center" />
</div>

<br><br>
<td><table border='0' align='center' width='25%'>
    <tr>
    <th nowrap><a href="http://www.jamonapi.com"><img src="images/jamon_small.jpg" id="monLink" border="0" /></a></th>
    <th nowrap>JAMon <%=MonitorFactory.getVersion()%></th>
    <th nowrap><a href="http://www.fdsapi.com"><img height=40 width=80 src="images/fds_logo_small.jpg" id="monLink" border="0" /></a></th>
    </tr>
</table></td>




</body>
</html>

<%
} else if ("xml".equalsIgnoreCase(outputType)) {
%>
<?xml version="1.0"?>
<%=outputText%>
<%
} else {
  response.setContentType("application/vnd.ms-excel");
%>


<%=outputText%>

<%
}
%>

<%!

Template jamonTemplate;

String[] outputTypeHeader={"outputTypeValue","outputType"};
Object[][] outputTypeBody={
                 {"html", "HTML"}, 
                 {"xml", "XML"}, 
                 {"csv", "Comma Separated"}, 
	         {"excel","MS Excel"}, 
                };

String[] actionHeader={"action","actionDisplay"};
Object[][] actionBody={
                 {"Refresh", "Refresh"}, 
                 {"Reset", "Reset"}, 
	         {"Enable","Enable"}, 
	         {"Disable","Disable"}, 
                };


String[] bufferSizeHeader={"bufferSize","bufferSizeDisplay"};
Object[][] bufferSizeBody={
                 {"No Action", "No Action"}, 
                 {"50", "50 rows"}, 
                 {"100", "100 rows"}, 
	         {"250","250 rows"}, 
               };


private static String enabled(boolean isEnabled) {
   return isEnabled ? "enabled" : "disabled";
}



// Format time String in current locale.
private String now() {
  return LocaleContext.getDateFormatter().format(new Date());
}



// if the value is null then return the passed in default else return the value
private static String getValue(String value, String defaultValue) {
  return (value==null || "".equals(value.trim())) ? defaultValue: value;
}

// convert arg to an int or return the default
private static int getNum(String value, String defaultValue) {

  String retValue=getValue(value, defaultValue);
  char[] digits=retValue.toCharArray();
  boolean isDigit=true;
  for (int i=0;i<digits.length;i++) {
     if (!Character.isDigit(digits[i]))
       isDigit=false;
  }

  if (!isDigit)
    retValue=defaultValue;

  return Integer.parseInt(retValue);
}


private static void executeAction(String action) {

  if ("Reset".equals(action))
    MonProxyFactory.resetExceptionDetail();
  else if ("Enable".equals(action)) 
    MonProxyFactory.enableExceptionDetail(true);
  else if ("Disable".equals(action))  
    MonProxyFactory.enableExceptionDetail(false);


}

// There is no technical limit to buffer size, so other possibilities could be added.
private static void setBufferSize(String bufferSize) {

  if ("50".equals(bufferSize))
    MonProxyFactory.setExceptionBufferSize(50);
  else if ("100".equals(bufferSize)) 
    MonProxyFactory.setExceptionBufferSize(100);
  else if ("250".equals(bufferSize)) 
    MonProxyFactory.setExceptionBufferSize(250);

}

private static ResultSetConverter getResultSetConverter(String[] header, Object[][] data, String arraySQLExec) {
     ArraySQL asql=new ArraySQL(header, arraySQLExec );

     ResultSetConverter rsc = new ResultSetConverter(header, asql.execute(data));
     //MonitorFactory.add("cellCount","count",rsc.getColumnCount()*rsc.getRowCount());
     return rsc;
}




private static ArrayConverter getArrayConverter(int textSize, String highlightMe) {

  // used to format the data in the report
  ArrayConverter ac=new ArrayConverter();
  // replace the normal extreme values of default min,max, and acccess date with an empty default.
  // If the key is in the data stream the value will be used instead of the key.

  DecimalFormat decimalFormat=LocaleContext.getFloatingPointFormatter();
  decimalFormat.applyPattern("#,###");
  DateFormat dateFormat=LocaleContext.getDateFormatter();

  // Set the converter to take action on data passed to the FormattedDataSet
  ac.setDefaultConverter(new ConverterNumToString(decimalFormat, new ConverterDateToString(dateFormat, new TruncateString(textSize,highlightMe,"#00ff99;"))));
 
  return ac;

}


private synchronized Template getJAMonTemplate(FormattedDataSet fds) {
   // start from sortedHTMLTable template and add some jamon display capabilities (highlighting and descriptive text appearing where the mouse is)
   if (jamonTemplate==null) {
     jamonTemplate=fds.getTemplate("sortedHTMLTable").copy();

     // highlighting for odd and even rows of the JAMon report.  Affects coloring, 
     // and what happens when the rows is highlighted with the mouse.
     String odd="Odd==   <tr class='odd' onMouseOver='rollOnRow(this, \"\")' onMouseOut='rollOffRow(this)'>\n";// label was removed from rollover due to red hightlighting messing it up
     String even="Even==   <tr class='even' onMouseOver='rollOnRow(this, \"\")' onMouseOut='rollOffRow(this)'>\n";
     jamonTemplate.initialize("BODY_ROW_PREFIX",0,0,"Type==Alternating "+odd+" "+even);
   }

   return jamonTemplate;
}

 public static class TruncateString implements Converter {
    Pattern pattern;

    int size;
    String stringToColorize;
    String color;
    public TruncateString(int size, String stringToColorize, String color) {
       this.size=size;
       this.stringToColorize=stringToColorize;
       this.color=color;
       if (stringToColorize!=null && !stringToColorize.equals(""))
         pattern=Pattern.compile("(?i)"+stringToColorize);

    }

    public Object convert(Object inputObj) {


       // Data input validation - if the passed object is null it is ok, but no logic needs to be performed. 
       if (inputObj==null)
         return null;
       else if (inputObj instanceof String && size>=1  && inputObj.toString().length()>size) { // prevent end of array bounds exception
        // truncate string and replace returns with returns/<br> for readability in browser and view source 
        String returnStr=inputObj.toString().substring(0,size).replaceAll("\n","\n<br>"); 
        if (pattern!=null) {
          Matcher matcher=pattern.matcher(returnStr);
          returnStr=matcher.replaceAll("<b style='color:black;background-color:"+color+"'>"+stringToColorize+"</b>");
        }
       
        return returnStr;
       } else if (inputObj instanceof String) {
        String returnStr=inputObj.toString().replaceAll("\n","\n<br>"); 
        if (pattern!=null) {
          Matcher matcher=pattern.matcher(returnStr);
          returnStr=matcher.replaceAll("<b style='color:black;background-color:"+color+"'>"+stringToColorize+"</b>");
        }
       
        return returnStr;    

       } else 
         return inputObj;

     }


  public Converter createInstance() {
    return new TruncateString(size, stringToColorize, color);
  } 

} 



%>